package com.engine.Mangers;

import java.util.Date;
import java.util.List;

import org.hibernate.Session;

import com.util.EngineUtil;
import com.wfe.db.SessionUtil;
import com.wfe.db.WorkFlowEngineQueryUtil;
import com.wfe.generics.BussinessTask;
import com.wfe.mapping.client.WfProjectStatus;
import com.wfe.mapping.client.WfProjectTask;
import com.wfe.mapping.client.WfProjectTaskStatus;
import com.wfe.mapping.client.WfTaskType;

/**
 * @author kareem_yehya
 * @since 29 March 2009 * @version 1.0.0.1
 * 
 *        1- Execute Rule when its status is assigned and task type 2 2- Update Rule Status after execution 3- Call Router to change next tasks status
 *        to assigned
 * */

public class RuleManger implements Runnable
{

	public void run()
	{

		while(true)
		{
			try
			{
				System.out.println("Enter Rule manger main Thread");
				List<WfProjectTask> taskList = loadAssignedRulesTasks(1000);
				if(taskList.size() > 0)
				{
					for(WfProjectTask projectTask : taskList)
					{
						boolean isSuccess = executeTask(projectTask);
						if(isSuccess)
						{
							WfProjectTask task = getWfProjectTaskById(projectTask.getRecid());
							Router.route(task);
						}

					}

				}

				Thread.sleep(500);
			}

			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}

	/**
	 * @author kareem_yehya
	 * @since 05 April 2009 <br>
	 *        Task Execute
	 * 
	 * 
	 * 
	 * */

	private boolean executeTask(WfProjectTask projectTask)
	{
		Class businessClass;
		try
		{
			businessClass = Class.forName(projectTask.getWfTask().getClazz());
		}catch(ClassNotFoundException e1)
		{

			e1.printStackTrace();
			return false;
		}
		try
		{

			BussinessTask task = (BussinessTask) businessClass.newInstance();
			task.setRecid(projectTask.getRecid());
			task.setCreationTime(projectTask.getCreationTime());
			task.setEndTime(projectTask.getEndTime());
			task.setStartTime(new Date());
			task.setWfPlanTask(projectTask.getWfPlanTask());
			task.setWfProject(projectTask.getWfProject());
			task.setWfTask(projectTask.getWfTask());
			task.setWfTaskType(projectTask.getWfTaskType());
			task.setWfProjectTaskStatus(getWfProjectTaskStatusByID(3));// Assigned
			// ------------------------
			changeTaskBeforeExecute(task);

			// -------------------
			task.execute();
			// --------------------
			changeTaskAfterExecute(task);
			return true;
		}catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}

	}

	private void changeTaskBeforeExecute(BussinessTask task)
	{
		WfProjectTask pTask = getWfProjectTaskById(task.getRecid());
		pTask.setWfProjectTaskStatus(getWfProjectTaskStatusByID(3l));
		pTask.setStartTime(new Date());
		pTask.setUserId(0l);
		pTask.setGroupId(0l);
		updateTask(pTask);

	}

	private void changeTaskAfterExecute(BussinessTask task)
	{
		WfProjectTask pTask = getWfProjectTaskById(task.getRecid());
		pTask.setIsProcessed(true);
		updateTask(pTask);

	}

	/**
	 * @author kareem_yehya
	 * @since 05 April 2009 <br>
	 *        Load unprocessed process tasks
	 * 
	 * 
	 * */
	// @SuppressWarnings("deprecation")
	public List<WfProjectTask> loadAssignedRulesTasks(int maxresults)
	{

		Session session = null;
		try
		{
			WfTaskType taskType = getwfTaskTypeByTypeID(2); // rule
			WfProjectTaskStatus taskStatus = getWfProjectTaskStatusByID(4); // assigned
			WfProjectStatus projectStatus = getWfProjectStatusByID(2); // inprocess
			session = SessionUtil.getSession();
			List<WfProjectTask> tasklist = WorkFlowEngineQueryUtil.getProjectTasks(session, projectStatus, maxresults, taskType, taskStatus, false);

			return tasklist;

		}

		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}finally
		{
			EngineUtil.closeSession(session);
		}

	}

	/**
	 * @author kareem_yehya
	 * @since 05 April 2009 <br>
	 *        Load Task Type
	 * 
	 * 
	 * */

	public WfTaskType getwfTaskTypeByTypeID(long tasktype)
	{

		Session session = null;
		try
		{

			session = SessionUtil.getSession();
			WfTaskType taskType = WorkFlowEngineQueryUtil.getWfTaskType(session, tasktype);
			return taskType;

		}

		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}finally
		{
			EngineUtil.closeSession(session);
		}

	}

	private WfProjectTaskStatus getWfProjectTaskStatusByID(long i)
	{

		Session session = null;
		try
		{

			session = SessionUtil.getSession();
			WfProjectTaskStatus projectTaskStatus = WorkFlowEngineQueryUtil.getWfProjectTaskStatusByID(i, session);
			return projectTaskStatus;

		}

		catch(Exception e)
		{

			e.printStackTrace();
			return null;
		}finally
		{

			EngineUtil.closeSession(session);
		}

	}

	private WfProjectTask getWfProjectTaskById(Long recid)
	{

		Session session = null;
		try
		{

			session = SessionUtil.getSession();
			WfProjectTask projectTask = WorkFlowEngineQueryUtil.getWfProjectTask(session, recid, 10).get(0);
			return projectTask;

		}

		catch(Exception e)
		{

			e.printStackTrace();
			return null;
		}finally
		{

			EngineUtil.closeSession(session);
		}

	}

	private void updateTask(WfProjectTask task)
	{

		Session session = null;
		try
		{

			session = SessionUtil.getSession();
			WorkFlowEngineQueryUtil.updateWfProjectTask(task, session);

		}

		catch(Exception e)
		{

			e.printStackTrace();

		}finally
		{

			EngineUtil.closeSession(session);
		}

	}

	private WfProjectStatus getWfProjectStatusByID(long i)
	{

		Session session = null;
		try
		{

			session = SessionUtil.getSession();
			WfProjectStatus projectStatus = WorkFlowEngineQueryUtil.getwfProjectStatusByID(i, session);

			return projectStatus;

		}

		catch(Exception e)
		{

			e.printStackTrace();
			return null;
		}finally
		{

			EngineUtil.closeSession(session);
		}

	}

	public static void main(String args[])
	{
		(new Thread(new RuleManger())).start();
	}

}
